<script>
	import { onMount, tick } from 'svelte';
	import Button from '$lib/Button.svelte';
	import { mockSongList } from './data';
	import { parseLyrics, SCROLL } from '../../utils/lyrics';
	import Scroll from './scroll.svelte';
	import Progress from '$lib/progress.svelte';
	import { rand, readableTime, throttle } from '../../../src/utils';

	let duration = 0;
	let buffered;
	let seekable;
	let seeking;
	let played;
	let ended;
	let currentTime = 0;
	let paused = false;
	let volume = 0.5;

	let lyricMode = SCROLL;

	let audioRef;
	function initAudioPlayer() {
		audioRef.addEventListener('ended', () => {
			if (currentMode === RANDOM_MODE) currentSongIndex = rand(list.length);
			if (currentMode === SINGLE_MODE) play();
			else nextSong();
		});
	}
	const play = () => {
		audioRef.play();
	};
	const pause = () => {
		audioRef.pause();
	};
	const playHandler = () => {
		if (paused) play();
		else pause();
	};

	/* 播放列表 */
	let list = [];
	let currentSongIndex = -1;
	function initSongList() {
		list = mockSongList.map((song) => {
			return { ...song, lyric: parseLyrics(song.lyric) };
		});
		currentSongIndex = 0;
	}
	$: currentSong = list[currentSongIndex];
	$: {
		if (audioRef) {
			audioRef.src = currentSong.src;
			play();
		}
	}
	$: currentLyric = currentSong?.lyric[lyricMode];

	/* 操作 */
	const add = (song) => (list = [...list, song]);
	const remove = (id) => (list = list.filter((item) => item.id !== id));
	const first = () => (list.length > 0 ? (currentSongIndex = 0) : (currentSongIndex = -1));
	const last = () => (currentSongIndex = list.length - 1);
	const nextSong = () => {
		currentSongIndex = (currentSongIndex + 1) % list.length;
	};
	const previousSong = () => {
		if (currentSongIndex <= 0) last();
		else currentSongIndex -= 1;
	};

	/* 播放模式 */
	const SINGLE_MODE = 'single';
	const SEQUENCE_MODE = 'sequence';
	const RANDOM_MODE = 'random';
	const modeList = [SINGLE_MODE, SEQUENCE_MODE, RANDOM_MODE];
	const modeIconList = ['danquxunhuan', 'shunxubofang', 'suijibofang'];
	let currentModeIndex = 0;
	const changeMode = () => {
		const size = modeList.length;
		currentModeIndex = (currentModeIndex + 1) % size;
	};
	$: currentMode = modeList[currentModeIndex];

	/* 进度 */
	const changeProgress = ({ detail }) => {
		if (detail != undefined && detail < duration) currentTime = detail * duration;
	};

	/* 音量 */
	let volumeBarRef;
	let isShowVolumeBar = false;
	$: {
		if (volumeBarRef) volumeBarRef.style.display = isShowVolumeBar ? 'block' : 'none';
	}
	const showVolumeBar = () => {
		isShowVolumeBar = true;
	};
	const hideVolumeBar = () => {
		isShowVolumeBar = false;
	};
	const volumeHandler = () => {
		if (isShowVolumeBar) hideVolumeBar();
		else showVolumeBar();
	};
	const changeVolume = ({ detail }) => {
		if (detail != undefined && detail >= 0 && detail <= 1) volume = detail;
	};

	/* 工具栏 */
	let toolbarRef;
	let isToolbarLocked = true;
	let isToolbarShow = true;
	$: {
		if (toolbarRef) toolbarRef.style.bottom = isToolbarShow ? '0' : '-64px';
	}
	const showToolbar = () => {
		isToolbarShow = true;
	};
	const hideToolbar = () => {
		if (!isToolbarLocked) {
			isToolbarShow = false;
		}
	};
	const mousemoveHandler = throttle((e) => {
		if (64 > document.documentElement.clientHeight - e.clientY) showToolbar();
		else hideToolbar();
	}, 100);
	const changeToolbarLock = () => {
		isToolbarLocked = !isToolbarLocked;
	};

	/* 关闭工具栏 */
	const clickOutsideHandler = (e) => {
		if (!toolbarRef?.contains(e.target)) {
			hideToolbar();
			hideVolumeBar();
		}
	};

	/* 初始化数据 */
	onMount(async () => {
		initSongList();
		initAudioPlayer();

		await tick();
		audioRef.play();
	});
</script>

<audio
	bind:this={audioRef}
	bind:duration
	bind:buffered
	bind:seekable
	bind:seeking
	bind:played
	bind:ended
	bind:currentTime
	bind:paused
	bind:volume
/>

<svelte:head>
	<title>Music</title>
</svelte:head>

<svelte:window on:mousemove={mousemoveHandler} on:click={clickOutsideHandler} />

<div class="container">
	<div class="music-box">
		<div class="left-area">
			<div class="picture">
				<img
					src={currentSong?.picture}
					alt=""
					width="100%"
					style={'animation-play-state:' + (paused ? 'paused' : 'running')}
				/>
			</div>

			<div class="controls">
				<Button on:click={previousSong} icon="shangyiqu" />
				<Button on:click={playHandler} icon={paused ? 'zanting' : 'bofangzhong'} size={'48px'} />
				<Button on:click={nextSong} icon="xiayiqu" />
			</div>
		</div>
		<div class="right-area">
			{#if lyricMode === SCROLL}
				<Scroll current={currentLyric?.current(currentTime)} content={currentLyric?.content} />
			{/if}
		</div>
	</div>

	<div
		class="music-toolbar"
		bind:this={toolbarRef}
		on:mouseover={showToolbar}
		on:focus={showToolbar}
	>
		<Button on:click={previousSong} icon="shangyiqu" />
		<Button on:click={playHandler} icon={paused ? 'zanting' : 'bofangzhong'} size={'42px'} />
		<Button on:click={nextSong} icon="xiayiqu" />
		<img src={currentSong?.picture} alt="" width="48px" height="48px" />
		<div class="progress">
			<Progress progress={currentTime / duration} on:change={changeProgress} />
			<span>{currentSong?.name}</span>
			<span>{currentSong?.artist}</span>
			<span>{readableTime(currentTime * 1000)} / {readableTime(duration * 1000)}</span>
		</div>

		<Button on:click={changeMode} icon={modeIconList[currentModeIndex]} />

		<div class="volume">
			<span class="volume-button">
				<Button on:click={volumeHandler} icon="yinliang" />
			</span>
			<span class="volume-bar" bind:this={volumeBarRef}>
				<Progress progress={volume} on:change={changeVolume} direction="vertical" />
			</span>
		</div>

		<Button on:click={changeToolbarLock} icon={isToolbarLocked ? 'lock' : 'unlock'} />
	</div>
</div>

<style lang="scss">
	.container {
		--bg-color: #f5f5f5;
		--text-color: #242424;
		--active-text-color: #c20c0c;

		--toolbar-height: 64px;
		--toolbar-bg-color: #242424;
		--toolbar-text-color: #fff;

		background: var(--bg-color);
		color: var(--text-color);
		height: 100%;

		@keyframes r {
			0% {
				transform: rotate(0deg);
			}
			50% {
				transform: rotate(180deg);
			}
			100% {
				transform: rotate(360deg);
			}
		}

		.music-box {
			margin-top: 10%;
			width: 100%;
			padding: 8px;
			box-sizing: border-box;
			display: flex;

			.left-area {
				flex: auto;
				.picture {
					margin: 0 auto;
					width: 400px;
					height: 400px;
					img {
						object-fit: cover;
						height: 100%;
						border-radius: 50%;
						animation: r 30s linear infinite;
					}
				}

				.controls {
					width: 100%;
					height: 80px;
					margin: 8px;
					display: flex;
					align-items: center;
					justify-content: center;
				}
			}

			.right-area {
				min-width: 500px;
				display: flex;
				align-items: center;
				// justify-content: space-around; // 会闪动
				// margin-left: 20%;
			}
		}

		.music-toolbar {
			position: fixed;
			left: 0;
			height: var(--toolbar-height);
			background: var(--toolbar-bg-color);
			color: var(--toolbar-text-color);
			width: 100%;
			display: flex;
			align-items: center;
			box-sizing: border-box;
			transition: bottom 0.5s;
			padding: 0 16px;

			img {
				margin: 8px;
			}
			.progress {
				flex: auto;
				margin: 16px 16px 0;
			}

			.volume {
				position: relative;

				.volume-bar {
					position: absolute;
					left: calc(50% - 0.5em);
					bottom: calc(var(--toolbar-height) - 10px);
					height: 150px;
					width: 1em;
				}
			}
		}
	}
</style>
